/**
 * 创建人:  @author huangpeng    
 * 创建时间:  2023年05月03日 14:03
 * 项目名称:  lemon-blog-cloud
 * 文件名称:  SysLoginWebService
 * 文件描述:  @Description: 前台登录信息service
 * 公司名称:  柠檬
 *
 * All rights Reserved, Designed By 柠檬 
 * @Copyright: 2022-2023
 *
 */
package com.lemon.auth.service;

import cn.hutool.core.util.StrUtil;
import com.lemon.auth.form.LoginBody;
import com.lemon.common.core.constant.*;
import com.lemon.common.core.domain.Result;
import com.lemon.common.core.enums.ResultEnums;
import com.lemon.common.core.enums.UserStatus;
import com.lemon.common.core.exception.ServiceException;
import com.lemon.common.core.text.Convert;
import com.lemon.common.core.utils.ServletUtils;
import com.lemon.common.core.utils.StringUtils;
import com.lemon.common.core.utils.ip.IpUtils;
import com.lemon.common.redis.service.RedisService;
import com.lemon.common.security.utils.SecurityUtils;
import com.lemon.system.api.RemoteLogService;
import com.lemon.system.api.RemoteUserService;
import com.lemon.system.api.domain.BiUser;
import com.lemon.system.api.domain.SysLogininfor;
import com.lemon.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 包名称：com.lemon.auth.service
 * 类名称：SysLoginWebService
 * 类描述：前台登录信息service
 * 创建人：@author huangpeng
 * 创建时间：2023年05月03日 14:03
 */
@Component
public class WebLoginService
{
    @Autowired
    private RemoteLogService remoteLogService;

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private RedisService redisService;

    /**
     * 登录
     */
    public LoginUser login(LoginBody form) {
        String password = form.getPassword();
        String loginName;
        BiUser user;
        LoginUser userInfo;
        Result<LoginUser> userResult;
        if (StrUtil.isNotEmpty(form.getLoginType())) {
            switch (form.getLoginType()) {
                case Constants.STR_ONE:
                    // 验证码校验移到网关模块,通过邮箱查询用户信息
                    userResult = remoteUserService.getInfoByEmail(form.getEmail(), SecurityConstants.INNER);
                    if (ResultEnums.ERROR.getCode() == userResult.getCode()) {
                        throw new ServiceException(userResult.getMsg());
                    }
                    if (StringUtils.isNull(userResult.getData())) {
                        recordLoginInfo(form.getUsername(), Constants.LOGIN_FAIL, "登录用户不存在");
                        throw new ServiceException("登录用户：" + form.getUsername() + " 不存在");
                    }
                    userInfo = userResult.getData();
                    user = userResult.getData().getBaseUser();
                    loginName = form.getEmail();
                    break;
                case Constants.STR_TWO:
                    // 验证码校验移到网关模块，通过手机号码查询用户信息
                    userResult = remoteUserService.getInfoByPhone(form.getPhone(), SecurityConstants.INNER);
                    if (ResultEnums.ERROR.getCode() == userResult.getCode()) {
                        throw new ServiceException(userResult.getMsg());
                    }
                    if (StringUtils.isNull(userResult.getData())) {
                        recordLoginInfo(form.getUsername(), Constants.LOGIN_FAIL, "登录用户不存在");
                        throw new ServiceException("登录用户：" + form.getUsername() + " 不存在");
                    }
                    userInfo = userResult.getData();
                    user = userResult.getData().getBaseUser();
                    loginName = form.getPhone();
                    break;
                default:
                    if (StringUtils.isNotEmpty(form.getUsername())) {
                        checkLoginNameAndPassword("用户名", form.getUsername(), password);
                        // 用户名不在指定范围内 错误
                        if (form.getUsername().length() < UserConstants.USERNAME_MIN_LENGTH
                                || form.getUsername().length() > UserConstants.USERNAME_MAX_LENGTH) {
                            recordLoginInfo(form.getUsername(), Constants.LOGIN_FAIL, "用户名不在指定范围");
                            throw new ServiceException("用户名不在指定范围");
                        }
                        // 通过用户编码查询用户信息
                        userResult = remoteUserService.getInfoByUserCode(form.getUsername(), SecurityConstants.INNER);
                        loginName = form.getUsername();
                    } else if (StringUtils.isNotEmpty(form.getEmail())) {
                        checkLoginNameAndPassword("邮箱", form.getEmail(), password);
                        // 通过邮箱查询用户信息
                        userResult = remoteUserService.getInfoByEmail(form.getEmail(), SecurityConstants.INNER);
                        loginName = form.getEmail();
                    } else if (StringUtils.isNotEmpty(form.getPhone())) {
                        checkLoginNameAndPassword("手机号码", form.getPhone(), password);
                        // 通过手机号码查询用户信息
                        userResult = remoteUserService.getInfoByPhone(form.getPhone(), SecurityConstants.INNER);
                        loginName = form.getPhone();
                    } else {
                        throw new ServiceException("用户名/邮箱/手机号码不能为空");
                    }
                    if (ResultEnums.ERROR.getCode() == userResult.getCode()) {
                        throw new ServiceException(userResult.getMsg());
                    }
                    if (StringUtils.isNull(userResult.getData())) {
                        recordLoginInfo(form.getUsername(), Constants.LOGIN_FAIL, "登录用户不存在");
                        throw new ServiceException("登录用户：" + form.getUsername() + " 不存在");
                    }
                    userInfo = userResult.getData();
                    user = userResult.getData().getBaseUser();
                    if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
                        recordLoginInfo(loginName, Constants.LOGIN_FAIL, "用户密码错误");
                        throw new ServiceException("用户不存在/密码错误");
                    }
                    break;
            }
        } else {
            throw new ServiceException("登陆类型不能为空！");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLoginInfo(loginName, Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + loginName + " 已停用");
        }
        if (UserStatus.LOCK.getCode().equals(user.getStatus())) {
            recordLoginInfo(loginName, Constants.LOGIN_FAIL, "用户已冻结，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + loginName + " 已冻结");
        }
        recordLoginInfo(loginName, Constants.LOGIN_SUCCESS, "登录成功");
        recordVisitorCount();
        return userInfo;
    }

    /**
     * 登出
     * @Title: logout
     * @Description: 登出
     * @param loginName
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2023/5/3 14:05
     */
    public void logout(String loginName) {
        recordLoginInfo(loginName, Constants.LOGOUT, "退出成功");
    }

    /**
     * 注册
     * @Title: register
     * @Description: 注册
     * @param user
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2023/5/3 14:05
     */
    public void register(BiUser user)
    {
        String userCode = user.getUserCode();
        String password = user.getPassword();
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(userCode, password))
        {
            throw new ServiceException("用户/密码必须填写");
        }
        if (userCode.length() < UserConstants.USERNAME_MIN_LENGTH
                || userCode.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            throw new ServiceException("账户长度必须在2到20个字符之间");
        }
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            throw new ServiceException("密码长度必须在5到20个字符之间");
        }

        // 注册用户信息
        Result<?> registerResult = remoteUserService.registerBaseUserInfo(user, SecurityConstants.INNER);
        if (ResultEnums.ERROR.getCode() == registerResult.getCode())
        {
            throw new ServiceException(registerResult.getMsg());
        }
        recordLoginInfo(user.getUserCode(), Constants.REGISTER, "注册成功");
    }

    /**
     * 记录登录信息
     *
     * @param userCode 用户名
     * @param status 状态
     * @param message 消息内容
     * @return
     */
    public void recordLoginInfo(String userCode, String status, String message)
    {
        SysLogininfor loginInfo = new SysLogininfor();
        loginInfo.setUserName(userCode);
        loginInfo.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
        loginInfo.setMsg(message);
        // 设置是前台登录
        loginInfo.setLoginType(Constants.LOGIN_TYPE_WEB);
        // 日志状态
        if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
        {
            loginInfo.setStatus(Constants.LOGIN_SUCCESS_STATUS);
        }
        else if (Constants.LOGIN_FAIL.equals(status))
        {
            loginInfo.setStatus(Constants.LOGIN_FAIL_STATUS);
        }
        remoteLogService.saveLogininfor(loginInfo, SecurityConstants.INNER);
    }

    /**
     * 记录访客数量
     * @Title: recordVisitorCount
     * @Description: 记录访客数量
     * @param
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2022/9/18 21:55
     */
    private void recordVisitorCount() {
        String visitorCount = Convert.toStr(redisService.getCacheObject(CacheConstants.VISITOR_COUNT_KEY));
        if (org.apache.commons.lang3.StringUtils.isBlank(visitorCount)) {
            redisService.deleteObject(CacheConstants.VISITOR_COUNT_KEY);
            redisService.setCacheObject(CacheConstants.VISITOR_COUNT_KEY, 1);
        } else {
            redisService.setCacheObject(CacheConstants.VISITOR_COUNT_KEY, Integer.parseInt(visitorCount) + 1);
        }
    }

    /**
     * 检查密码的长度是否合法
     * @Title: checkLoginNameAndPassword
     * @Description: 检查密码的长度是否合法
     * @param loginTypeName 登陆类型名称
     * @param loginName 登录名
     * @param password 密码
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2023/11/19 20:44
     */
    private void checkLoginNameAndPassword(String loginTypeName, String loginName, String password) {
        if (StringUtils.isAnyBlank(loginName, password)) {
            recordLoginInfo(loginName, Constants.LOGIN_FAIL,  loginTypeName + "/密码必须填写");
            throw new ServiceException(loginTypeName + "/密码必须填写");
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            recordLoginInfo(loginName, Constants.LOGIN_FAIL, "用户密码不在指定范围");
            throw new ServiceException("用户密码不在指定范围");
        }
    }

}